package com.zhi.controller;

import com.zhi.config.Constant;
import com.zhi.entity.*;
import com.zhi.service.*;
import com.zhi.util.PageUtil;
import com.zhi.util.PubFun;
import com.zhi.util.UpdateObjectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpSession;
import java.sql.Date;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 请假教师逻辑Controller层
 */
@Controller
public class LeaveTeacherController {

    Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
    TeacherService teacherService;

    @Autowired
    StudentService studentService;

    @Autowired
    GradeService gradeService;

    @Autowired
    GradeTeacherService gradeTeacherService;

    @Autowired
    LeaveService leaveService;

    @Autowired
    LeaveInfoService leaveInfoService;

    @Autowired
    DictionaryService dictionaryService;

    @Autowired
    MailService mailService;

    //邮件模板
    @Value("${email.template02}")
    String emailTemplate02;

    @Value("${email.template03}")
    String emailTemplate03;

    /**
     * 列表数据-指导员审批
     * @param model
     * @param pageUtil
     * @return
     */
    @RequestMapping("/toLeaveInstructor")
    public String toLeaveInstructor(Model model, PageUtil pageUtil, HttpSession httpSession) {

        //获得搜索框输入的条件
        String searchStudentId = pageUtil.getPara01();
        String searchGradeId = pageUtil.getPara02();

        //思路：1根据session中教师的信息，2得到教师工号，3在得到所管班级编号，4再得到该班级下学生ids，5再得到请假申请列表
        //1.从session获取登录教师的信息
        //1.1根据session中教师的信息
        //Teacher sessionTeacher = new Teacher("2001201600001",null,null,null,null);
        Teacher sessionTeacher = (Teacher)httpSession.getAttribute("sessionTeacher");

        //1.2得到教师工号
        String teacherId = sessionTeacher.getTeacherId();
        //1.3得到所管班级编号(考虑一个指导员管多个班级)
        Grade grade = new Grade(null,null,null,teacherId,null);
        List<Grade> grades = gradeService.findAll(grade);
        List<String> studentIdList = new ArrayList<>();//存该指导员所管的学生id集合
        studentIdList.add("0000");//防止list为空sql报错
        for(Grade fg : grades){
            String gradeId = fg.getGradeId();

            //若查询条件有班级gradeId，且选择的班级searchGradeId与循环的gradeId不等，不处理继续下次循环。
            //若查询条件无班级gradeId，正常循环查询
            if(PubFun.isNotNull(searchGradeId) && !searchGradeId.equals(gradeId)){
                continue;
            }
            //1.4再得到该班级下学生ids
            Student student = new Student();
            student.setGradeId(gradeId);
            List<Student> students = studentService.findAll(student);
            for(Student stu : students){
                String studentId = stu.getStudentId();

                //若查询条件有studentId，且查询的searchStudentId与循环的studentId不等，不处理继续下次循环。
                //若查询条件无studentId，正常循环查询
                if(PubFun.isNotNull(searchStudentId) && !searchStudentId.equals(studentId)){
                    continue;
                }
                //将学生id加入list
                studentIdList.add(studentId);
            }
        }

    	//2、初始化分页工具
    	pageUtil = PageUtil.init(pageUtil);
    	Pageable pageable = PageRequest.of(pageUtil.getPageIndex()-1, pageUtil.getSize());
    	
    	//3、查询分页数据
        List<String> stateList = new ArrayList<>();
        stateList.add("0");//申请中
    	Page<ALeave> pageList=leaveService.getEntityListWithCodeName(pageable,studentIdList,stateList);
    	List<ALeave> leaves = pageList.getContent();
        
        //4、设置总页数
    	pageUtil.setTotalPages(pageList.getTotalPages());
    	
    	//5、返回前台数据
    	model.addAttribute("pageUtil", pageUtil);
        model.addAttribute("leaves", leaves);
        model.addAttribute("grades", grades);
        return "leaveTeacher/leaveInstructorList";
    }

    /**
     * 列表数据-指导员历史审核
     * @param model
     * @param pageUtil
     * @return
     */
    @RequestMapping("/toLeaveInstructorHistory")
    public String toLeaveInstructorHistory(Model model,PageUtil pageUtil,HttpSession httpSession) {

        //获得搜索框输入的条件
        String searchStudentId = pageUtil.getPara01();
        String searchGradeId = pageUtil.getPara02();

        //思路：1根据session中教师的信息，2得到教师工号，3在得到所管班级编号，4再得到该班级下学生ids，5再得到请假申请列表
        //1.从session获取登录教师的信息
        //1.1根据session中教师的信息
        //Teacher sessionTeacher = new Teacher("2001201600001",null,null,null,null);
        Teacher sessionTeacher = (Teacher)httpSession.getAttribute("sessionTeacher");

        //1.2得到教师工号
        String teacherId = sessionTeacher.getTeacherId();
        //1.3得到所管班级编号(考虑一个指导员管多个班级)
        Grade grade = new Grade(null,null,null,teacherId,null);
        List<Grade> grades = gradeService.findAll(grade);
        List<String> studentIdList = new ArrayList<>();//存该指导员所管的学生id集合
        studentIdList.add("0000");//防止list为空sql报错
        for(Grade fg : grades){

            String gradeId = fg.getGradeId();

            //若查询条件有班级gradeId，且选择的班级searchGradeId与循环的gradeId不等，不处理继续下次循环。
            //若查询条件无班级gradeId，正常循环查询
            if(PubFun.isNotNull(searchGradeId) && !searchGradeId.equals(gradeId)){
                continue;
            }

            //1.4再得到该班级下学生ids
            Student student = new Student();
            student.setGradeId(gradeId);
            List<Student> students = studentService.findAll(student);
            for(Student s : students){
                String studentId = s.getStudentId();

                //若查询条件有studentId，且查询的searchStudentId与循环的studentId不等，不处理继续下次循环。
                //若查询条件无studentId，正常循环查询
                if(PubFun.isNotNull(searchStudentId) && !searchStudentId.equals(studentId)){
                    continue;
                }

                studentIdList.add(studentId);
            }
        }

        //2、初始化分页工具
        pageUtil = PageUtil.init(pageUtil);
        Pageable pageable = PageRequest.of(pageUtil.getPageIndex()-1, pageUtil.getSize());

        //3、查询分页数据
        List<String> stateList = new ArrayList<>();
        stateList.add("1");//同意
        stateList.add("2");//拒绝
        stateList.add("3");//申请超期的请假单
        Page<ALeave> pageList=leaveService.getEntityListWithCodeName(pageable,studentIdList,stateList);
        List<ALeave> leaves = pageList.getContent();

        //4、设置总页数
        pageUtil.setTotalPages(pageList.getTotalPages());

        //5、返回前台数据
        model.addAttribute("pageUtil", pageUtil);
        model.addAttribute("leaves", leaves);
        model.addAttribute("grades", grades);
        return "leaveTeacher/leaveInstructorHistory";
    }

    /**
     * 列表数据-任课教师历史请假记录
     * 任课教师只能查看学生申请请假时选择了他的的请假单，只需要根据教师工号，查询LeaveInfo请假子表
     * @param model
     * @param pageUtil
     * @return
     */
    @RequestMapping("/toLeaveTeacherHistory")
    public String toLeaveTeacher(Model model,PageUtil pageUtil,HttpSession httpSession) {

        //获得搜索框输入的条件
        String searchStudentId = pageUtil.getPara01();
        String searchGradeId = pageUtil.getPara02();

        //思路：1根据session中教师的信息，2得到教师工号，3查请假子表得到涉及的请假编号，4再得到请假申请列表
        //1.从session获取登录教师的信息
        //1.1根据session中教师的信息
        //Teacher sessionTeacher = new Teacher("2001201600001",null,null,null,null);
        Teacher sessionTeacher = (Teacher)httpSession.getAttribute("sessionTeacher");

        //1.2得到教师工号
        String teacherId = sessionTeacher.getTeacherId();

        //1.3查请假子表得到涉及的请假编号
        ALeaveInfo aLeaveInfo = new ALeaveInfo(null,null,teacherId);
        List<ALeaveInfo> aLeaveInfos = leaveInfoService.findAll(aLeaveInfo);
        List<Integer> aLeaveIdList = new ArrayList<>();
        aLeaveIdList.add(1111);//防止list为空sql报错
        for(ALeaveInfo ai : aLeaveInfos){
            Integer aLeaveId = ai.getLeaveId();

            //1.4判断查询条件有无班级并处理
            if(PubFun.isNotNull(searchGradeId)){
                //太复杂了，都不知道怎么实现了1
                //已有搜索班级id：根据请假单id获得请假单，再获得StudentId，再根据学生id去Student表获得学生班级，匹配两个班级是否一致，一致则继续，不一致continue
                ALeave aLeave = leaveService.getOne(aLeaveId);
                Student student = studentService.getOne(aLeave.getStudentId());
                String studentGradeId = student.getGradeId();
                if(!searchGradeId.equals(studentGradeId)){
                    continue;//程序走到这，说明循环的请假单不是这个班级的，continue跳过不处理
                }
            }

            //1.5判断查询条件有无学号并处理
            if(PubFun.isNotNull(searchStudentId)){
                //太复杂了，都不知道怎么实现了2
                //用aLeaveId与searchStudentId去查，此请假单是此学生的，就往list添加，否则直接continue
                ALeave aLeave = new ALeave();
                aLeave.setId(aLeaveId);
                aLeave.setStudentId(searchStudentId);
                List<ALeave> aLeaves = leaveService.findAll(aLeave);
                if(aLeaves.size()==0){
                    continue;//程序走到这，说明循环的请假单不是搜索的学生的，continue跳过不处理
                }
            }
            //1.6将请假单id加入list，表示满足条件要查询的请假单
            aLeaveIdList.add(aLeaveId);//请假编号id的list集合
        }

        //2、初始化分页工具
        pageUtil = PageUtil.init(pageUtil);
        Pageable pageable = PageRequest.of(pageUtil.getPageIndex()-1, pageUtil.getSize());

        //3、查询分页数据
        List<String> stateList = new ArrayList<>();
        stateList.add("1");//同意
        Page<ALeave> pageList=leaveService.getEntityListWithCodeName2(pageable,aLeaveIdList,stateList);
        List<ALeave> leaves = pageList.getContent();

        //4、查询该教师任课班级，非指导员所带班级
        GradeTeacher gradeTeacher = new GradeTeacher(null,null,teacherId);
        List<GradeTeacher> gradeTeachers = gradeTeacherService.findAll(gradeTeacher);
        List<String> gradeIds = new ArrayList<>();
        for(GradeTeacher gt : gradeTeachers){
            gradeIds.add(gt.getGradeId());
        }
        List<Grade> grades = gradeService.findAllById(gradeIds);

        //5、设置总页数
        pageUtil.setTotalPages(pageList.getTotalPages());

        //6、返回前台数据
        model.addAttribute("pageUtil", pageUtil);
        model.addAttribute("leaves", leaves);
        model.addAttribute("grades", grades);

        return "leaveTeacher/leaveTeacherHistory";
    }

    /**
     * 请假单审核详情页面
     * 根据type值不通，跳转不通的页面，审核页面审核在途流程，历史记录页面只查看完结的流程
     * @param model
     * @param id
     * @return
     */
    @RequestMapping("/leaveTeacher/toLeaveInstructorInfo")
    public String toLeaveInstructorInfo(Model model,Integer id,String type) {

        //1.根据请假id查询请假主表信息，请假单信息
        ALeave aleave = leaveService.getOne(id);

        //2.根据请假id查询请假子表信息请假申请教师id，再获得教师信息，用于下拉选哪些选中
        ALeaveInfo aLeaveInfo = new ALeaveInfo(null,id,null);
        List<ALeaveInfo> aLeaveInfos = leaveInfoService.findAll(aLeaveInfo);
        String aLeaveInfoTeachers = "";
        for(ALeaveInfo ali : aLeaveInfos){
            aLeaveInfoTeachers = aLeaveInfoTeachers +"," +ali.getTeacherId();
        }
        aleave.setTeacherIds(aLeaveInfoTeachers);

        //3.根据请假学生id，再获得学生信息，再获得班级信息，再获得班级教师id，再获得教师信息，用于下拉选所有选项
        //3.1根据请假主表，获得学生id，再获得学生对象及其学号，再获得其班级编号
        String studentId = aleave.getStudentId();
        Student student = studentService.getOne(studentId);
        String facultyGradeId =student.getGradeId();

        //3.2根据班级编号获得FacultyGradeTeacher表中其班级的所有任课教师ids
        GradeTeacher gradeTeacher = new GradeTeacher(null,facultyGradeId,null);
        List<GradeTeacher> gradeTeachers = gradeTeacherService.findAll(gradeTeacher);

        //3.3根据教师ids查询教师详细信息
        List<String> ids = new ArrayList<String>();
        ids.add("0000");//防止list空sql报错
        //遍历facultyGradeTeachers取出教师对象
        for(GradeTeacher fgt : gradeTeachers){
            String teacherId = fgt.getTeacherId();
            ids.add(teacherId);
        }
        List<Teacher> teachers = teacherService.findAllById(ids);

        //4.重新将班级名字及学生名字赋值到学生id上用以显示学生名字
        Grade grade = gradeService.getOne(student.getGradeId());
        aleave.setStudentName(grade.getGradeName()+"--"+student.getName());

        //5.若为指导员查看历史请假记录详情，leave的state需要将编码替换成对应的值
        if("history".equals(type)){
            List<Dictionary> dicts = dictionaryService.findByCodeTypeAndCode("leaveState",aleave.getState());
            Dictionary dict = dicts.get(0);
            dict = dict == null?new Dictionary():dict;
            String stateName = dict.getCodeName();
            aleave.setState(stateName);

        }

        model.addAttribute("teachers",teachers);
        model.addAttribute("leave", aleave);

        if("apply".equals(type)){
            //type='apply'
            return "leaveTeacher/leaveInstructorInfo";
        }else{
            //type='history'
            return "leaveTeacher/leaveInstructorHistoryInfo";
        }

    }

    /**
     * 请假流程审核，只处理请假主表，审核意见及审核结果，其他字段不处理
     * @param leave
     * @return
     */
    @RequestMapping("/leaveTeacher/audit")
    public String audit(ALeave leave) {

        //设置审核时间
        leave.setAuditDate(new Date(System.currentTimeMillis()));

        Integer leaveId = leave.getId();
        ALeave sourceALeave = leaveService.getOne(leaveId);
        //使用工具，将页面leave对象不为空的值，赋值到数据源sourceALeave中并存储
        UpdateObjectUtil.copyNullProperties(leave,sourceALeave);
        leaveService.edit(sourceALeave);

        //不论同意还是拒绝，给学生发邮件
        //获得审核结果中文
        String auditResult = dictionaryService.findByCodeTypeAndCode("leaveState",sourceALeave.getState()).get(0).getCodeName();

        Student student = studentService.getOne(sourceALeave.getStudentId());
        String instructorName = teacherService.getOne(student.getGrade().getInstructor()).getName();
        String studentEmail = student.getEmail();
        String title = Constant.EMAIL_TITLE;

        Map<String,String> params = new HashMap<>();
        params.put("instructorName",instructorName);
        params.put("studentName",student.getName());
        params.put("reason",sourceALeave.getReason());
        params.put("startDate",PubFun.getString(sourceALeave.getStartDate()));
        params.put("endDate",PubFun.getString(sourceALeave.getEndDate()));
        params.put("applyDate",PubFun.getString(sourceALeave.getApplyDate()));
        params.put("opinion",PubFun.getString(sourceALeave.getOpinion()));
        params.put("auditResult",auditResult);

        String contentForStudent = PubFun.getEmailContent(emailTemplate02,params);

        mailService.sendMail(title,contentForStudent,studentEmail);

        //若审核结论是：1-同意请假，则此处给该次请假涉及的教师发送请假邮件
        String auditState = sourceALeave.getState();
        if("1".equals(auditState)){
            ALeaveInfo aLeaveInfo = new ALeaveInfo(null,leaveId,null);
            List<ALeaveInfo> aLeaveInfos = leaveInfoService.findAll(aLeaveInfo);

            List<String> ids = new ArrayList<String>();
            ids.add("0000");//防止list空sql报错
            //遍历aLeaveInfos取出教师对象
            for(ALeaveInfo ai : aLeaveInfos){
                String teacherId = ai.getTeacherId();
                ids.add(teacherId);
            }
            List<Teacher> teachers = teacherService.findAllById(ids);
            for(Teacher teacher : teachers){
                String teacherEmail = teacher.getEmail();
                //调用发送邮件
                //其他参数上边发学生已经补齐
                params.put("teacherName",teacher.getName());
                params.put("gradeName",student.getGrade().getGradeName());

                String contentForTeacher = PubFun.getEmailContent(emailTemplate03,params);

                mailService.sendMail(title,contentForTeacher,teacherEmail);
            }

        }

        return "redirect:/toLeaveInstructor";
    }

    
}
